<template>
    <div>
        <!-- 三级分类全局组件 -->
        <Category :scene="scene"></Category>
        <el-card style="margin: 10px 0px;">
            <div v-show="scene==0">
                <el-button type="primary" size="default" icon="Plus" :disabled="categoryStore.c3Id?false:true" @click="addAttr" v-has="`btn.Attr.add`">添加属性</el-button>
                <el-table border style="margin: 10px 0px;" :data="attrArr">
                    <el-table-column label="序号" type="index" align="center" width="80px"></el-table-column>
                    <el-table-column label="属性名称" width="120px" prop="attrName"></el-table-column>
                    <el-table-column label="属性值名称">
                        <template #="{row}">
                            <el-tag style="margin: 5px;" v-for="item in row.attrValueList" :key="item.id">{{ item.valueName }}</el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column label="操作" width="120px">
                        <template #="{row}">
                            <!-- 修改已有属性的按钮 -->
                            <el-button type="primary" size="small" icon="Edit" @click="updateAttr(row)" v-has="`btn.Attr.update`"></el-button>
                            <el-popconfirm :title="`你确定删除${row.attrName}?`" @confirm="deleteAttr(row.id)">
                                <template #reference>
                                    <el-button type="primary" size="small" icon="Delete" v-has="`btn.Attr.remove`"></el-button>
                                </template>
                            </el-popconfirm>
                        </template>
                    </el-table-column>
                </el-table>
            </div>
            <div v-show="scene==1">
                <!-- 展示添加属性与修改属性的结构 -->
                <el-form :inline="true">
                    <el-form-item label="属性名称">
                        <el-input placeholder="请您输入属性名称" v-model="attrParams.attrName"></el-input>
                    </el-form-item>
                </el-form>
                <el-button type="primary" size="default" icon="Plus" :disabled="attrParams.attrName?false:true" @click="addAttrValue">添加属性值</el-button>
                <el-button type="primary" size="default" @click="cancel">取消</el-button>
                <el-table border style="margin: 10px 0px;" :data="attrParams.attrValueList">
                    <el-table-column width="80px" type="index" label="序号" align="center"></el-table-column>
                    <el-table-column label="属性值名称">
                        <!-- row为当前属性值对象 -->
                        <template #="{row,$index}">
                            <el-input placeholder="请你输入属性值名字" v-model="row.valueName" v-if="row.flag" @blur="toLook(row,$index)" size="small" :ref="(vc:any)=>inputAttr[$index]=vc"></el-input>
                            <div v-else @click="toEdit(row,$index)">{{ row.valueName }}</div>
                        </template>
                    </el-table-column>
                    <el-table-column label="属性值操作">
                        <template #="row,$index">
                            <el-button type="primary" size="small" icon="Delete" @click="attrParams.attrValueList.splice($index,1)"></el-button>
                        </template>
                    </el-table-column>
                </el-table>
                <el-button type="primary" size="default" @click="save" :disabled="attrParams.attrValueList.length>0?false:true">保存</el-button>
                <el-button type="primary" size="default" @click="cancel">取消</el-button>
            </div>
        </el-card>
    </div>
</template>

<script lang="ts" setup name="Attr">
    // 引入分类的仓库
    import useCategoryStore from '@/store/modules/category'
    // 引入watch
    import {watch,ref,reactive,nextTick,onBeforeUnmount} from 'vue'
    // 引入获取属性与属性值的接口方法
    import {reqAttr,reqAddOrUpdateAttr,reqRemoveAttr} from '@/api/product/attr'
    import type {AttrResponseData,Attr,AttrValue} from '@/api/product/attr/type'
    import { ElMessage } from 'element-plus'

    // 获取分类的仓库
    let categoryStore=useCategoryStore()
    // 定义card组件内容切换的变量
    let scene=ref<number>(0) // scene为0，显示tale scene为1，显示添加与修改属性结构
    // 存储已有的属性与属性值
    let attrArr=ref<Attr[]>([])
    // 收集新增的属性的对象
    let attrParams=reactive<Attr>({
        attrName: '', // 新增的属性的名字
        attrValueList: [], // 新增的属性值的数组
        categoryId: '', // 三级分类的ID
        categoryLevel: 3  // 代表的是三级分类
    })
    // 存储将来获取的el-input组件实例
    let inputAttr=ref<any>([])

    
    // 监听仓库中的三级分类ID变化
    watch(()=>categoryStore.c3Id, ()=>{
        // 清空上一次查询到的属性值
        attrArr.value=[]
        // 要保证三级分类有才能发请求
        if(categoryStore.c3Id){
            getAttr()
        }
    })

    // 获取已有属性与属性值方法
    async function getAttr(){
        // 获取分类的ID
        const {c1Id,c2Id,c3Id}=categoryStore
        // 获取分类下已有的属性和属性值
        let result:AttrResponseData=await reqAttr(c1Id,c2Id,c3Id)
        if(result.code==200){
            attrArr.value=result.data
        }
    }

    // 添加属性按钮的回调
    function addAttr(){
        // 每次点击前先清空数据再收集数据
        Object.assign(attrParams,{
            attrName: '', 
            attrValueList: [], 
            categoryId: '', 
            categoryLevel: 3  
        })
        // 切换为添加与修改属性的结构
        scene.value=1
    }

    // 修改属性按钮的回调
    function updateAttr(row:Attr){
        scene.value=1
        // 将已有的属性对象赋值给attrParams对象即可
        // Object.assign是浅拷贝，attrParams和row指向同一个对象。必须要进行深拷贝
        Object.assign(attrParams,JSON.parse(JSON.stringify(row)))
    }

    // 取消按钮的回调
    function cancel(){
        scene.value=0
    }

    // 添加属性值按钮的回调
    function addAttrValue(){
        // 点击添加属性值按钮的时候，向数组中添加一个属性值对象
        attrParams.attrValueList.push({
            valueName:'',
            flag:true // 控制编辑模式与查看模式的切换
        })
        // 获取最后的el-input组件聚焦
        nextTick(()=>{
            inputAttr.value[attrParams.attrValueList.length-1].focus()
        })
    }

    // 保存按钮的回调
    async function save(){
        // 收集参数
        // 收集新增的三级分类的Id
        attrParams.categoryId=categoryStore.c3Id
        // 发送请求
        let result:any=await reqAddOrUpdateAttr(attrParams)
        // 添加属性值或修改属性值成功
        if(result.code==200){
            // 切换场景
            scene.value=0
            // 提示信息
            ElMessage({
                type:'success',
                message:attrParams.id?'修改成功':'添加成功'
            })
            // 获取已有的全部属性与属性值
            getAttr()
        }else{
            ElMessage({
                type:'error',
                message:attrParams.id?'修改失败':'添加失败'
            })
        }
    }

    // 属性值表单元素失去焦点的回调
    function toLook(row:AttrValue,$index:number){
        // 非法情况1:属性值不能为空
        if(row.valueName.trim()==''){
            // 删除掉对应属性值为空的元素
            attrParams.attrValueList.splice($index,1)
            // 提示信息
            ElMessage({
                type:'error',
                message:'属性值不能为空'
            })
            return
        }
        // 非法清空二：属性值不能重复
        let repeat=attrParams.attrValueList.find((item)=>{
            // 要把当前失去焦点的属性值对象从当前数组扣出去
            if(item!=row){
                return item.valueName===row.valueName
            }
        })
        if(repeat){
            // 将重复的属性值从数组中删掉
            attrParams.attrValueList.splice($index,1)
            // 提示信息
            ElMessage({
                type:'error',
                message:'属性值不能重复'
            })
            return
        }
        // 相应的属性值对象flag变为false，展示div
        row.flag=false
    }

    // div点击回调
    function toEdit(row:AttrValue,$index:number){
        // 展示input
        row.flag=true
        // nextTick:响应式数据发生变化，获取更新的DOM(组件实例)
        nextTick(()=>{
            inputAttr.value[$index].focus()
        })
    }

    // 删除某个已有属性的回调
    async function deleteAttr(attrId:number){
        // 发相应的已有属性的请求
        let result:any=await reqRemoveAttr(attrId)
        if(result.code==200){
            ElMessage({
                type:'success',
                message:'删除成功'
            })
            // 获取已有属性与属性值
            getAttr()
        }else{
            ElMessage({
                type:'error',
                message:'删除失败'
            })
        }
    }

    // 当路由组件切换跳转销毁时，把仓库分类相关数据清空
    onBeforeUnmount(()=>{
        // 清空分类仓库的数据
        categoryStore.$reset()
    })

</script>

<style scoped lange="scss">
    
</style>